package encaps.utils.search;

import encaps.action.*;
import encaps.entities.Movie;
import encaps.entities.MovieLocal;
import encaps.entities.MovieLocalHome;
import encaps.entities.Role;
import encaps.resources.Grants;
import encaps.resources.Labels;
import encaps.resources.Response;
import encaps.utils.EntityUtil;
import encaps.utils.StringUtil;
import encaps.utils.SystemException;
import encaps.utils.XMLHelper;
import java.text.DecimalFormat;
import java.util.Collection;
import javax.ejb.FinderException;
import javax.naming.NamingException;
import org.jdom.Element;

public class MovieSearcher extends Searcher {

    public MovieSearcher() {
        basicSearchHeaderPattern = Labels.getLabel(Labels.BASIC_MOVIE_SEARCH_HEADER_PATTERN);
    }

    @Override
    public Element headersToXMLElement() {
        Element headers = XMLHelper.createElement(Response.COLUMN_HEADERS);

        Element loginHeader = XMLHelper.addChild(headers, Response.COLUMN_HEADER);
        XMLHelper.addChild(loginHeader, Response.COLUMN_HEADER_LABEL, Labels.getLabel(Labels.MOVIE_TITLE));
        XMLHelper.addChild(loginHeader, Response.COLUMN_NAME, Movie.TITLE);

        Element worldCasheader = XMLHelper.addChild(headers, Response.COLUMN_HEADER);
        XMLHelper.addChild(worldCasheader, Response.COLUMN_HEADER_LABEL, Labels.getLabel(Labels.MOVIE_CASH));
        XMLHelper.addChild(worldCasheader, Response.COLUMN_NAME, Movie.WORLDCASH);

        Element contactsHeader = XMLHelper.addChild(headers, Response.COLUMN_HEADER);
        XMLHelper.addChild(contactsHeader, Response.COLUMN_HEADER_LABEL, Labels.getLabel(Labels.MOVIE_RATING));
        XMLHelper.addChild(contactsHeader, Response.COLUMN_NAME, Movie.RATING);

        return headers;
    }

    @Override
    protected Element searchResultToTableRows(Collection movies, Role role) {
        Element rows = XMLHelper.createElement(Response.ROWS);
        for (Object obj : movies) {
            MovieLocal movie = (MovieLocal) obj;
            Element row = XMLHelper.addChild(rows, Response.ROW);
            //Добавление ячеек в строку таблицы. Каждая ячейка соответствует
            //одному полю (одной колонке) таблицы
            Element titleCell = XMLHelper.addChild(row, Response.CELL, movie.getTitle());
            titleCell.setAttribute(Response.TYPE, Response.TEXT);

            DecimalFormat df = new DecimalFormat("###,###,###,##0");
            Element cashCell = XMLHelper.addChild(row, Response.CELL, df.format(movie.getWorldCash()));
            cashCell.setAttribute(Response.TYPE, Response.TEXT);

            df = new DecimalFormat("0.##");
            Element ratingCell = XMLHelper.addChild(row, Response.CELL, df.format(movie.getRating()));
            ratingCell.setAttribute(Response.TYPE, Response.TEXT);
            //Добавляем ссылки на действия над фильмами
            //Ссылка на просмотр
            Element viewLinkCell = XMLHelper.addChild(row, Response.CELL);
            viewLinkCell.setAttribute(Response.TYPE, Response.LINK);
            viewLinkCell.addContent(XMLHelper.createLink(Labels.getLabel(Labels.VIEW_LINK), ViewMovieAction.VIEW_MOVIE, movie.getId()));
            //Ссылка на редактирование
            if (role.hasGrant(Grants.EDIT_MOVIE)) {
                Element editLinkCell = XMLHelper.addChild(row, Response.CELL);
                editLinkCell.setAttribute(Response.TYPE, Response.LINK);
                editLinkCell.addContent(XMLHelper.createLink(Labels.getLabel(Labels.EDIT_LINK), EditMovieAction.EDIT_MOVIE, movie.getId()));
            }
            //Ссылка на удаление
            if (role.hasGrant(Grants.DELETE_MOVIE)) {
                Element deleteLinkCell = XMLHelper.addChild(row, Response.CELL);
                deleteLinkCell.setAttribute(Response.TYPE, Response.LINK);
                deleteLinkCell.addContent(XMLHelper.createLink(Labels.getLabel(Labels.DELETE_LINK), DeleteMovieAction.DELETE_MOVIE, movie.getId()));
            }
        }
        return rows;
    }

    @Override
    protected Collection find(SearchContext context) throws SystemException {
        try {
            MovieLocalHome movieHome = EntityUtil.getMovieHome();

            int recordsPerPage = context.getRecordsPerPage();
            int fromRecord = context.getFromRecord();
            Collection<MovieLocal> result = null;
            if (context.isBasicSearch()) {
                String searchParameter = context.getSearchParameter(BasicSearchAction.SEARCH_PARAMETER);
                result = movieHome.findPaged(searchParameter, context.getOrderColumn(), context.getOrderType(), fromRecord, recordsPerPage);
            } else {
                String title = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.TITLE));
                String countries = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.COUNTRIES));
                String genre = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.GENRE));
                String person = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.PERSON));
                String studio = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.STUDIO));
                Double ratingMin = StringUtil.parseDouble(context.getSearchParameter(AdvancedMovieSearchAction.RATING_MIN));
                Double ratingMax = StringUtil.parseDouble(context.getSearchParameter(AdvancedMovieSearchAction.RATING_MAX));
                String description = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.DESCRIPTION));
                Integer budgetMin = StringUtil.parseInteger(context.getSearchParameter(AdvancedMovieSearchAction.BUDGET_MIN));
                Integer budgetMax = StringUtil.parseInteger(context.getSearchParameter(AdvancedMovieSearchAction.BUDGET_MAX));
                Integer cashMin = StringUtil.parseInteger(context.getSearchParameter(AdvancedMovieSearchAction.WORLD_CASH_MIN));
                Integer cashMax = StringUtil.parseInteger(context.getSearchParameter(AdvancedMovieSearchAction.WORLD_CASH_MAX));

                result = movieHome.findByParametersPaged(title, countries, genre,
                        person, studio, ratingMin, ratingMax, description, budgetMin,
                        budgetMax, cashMin, cashMax, context.getOrderColumn(),
                        context.getOrderType(), fromRecord, recordsPerPage);
            }
            return result;
        } catch (NamingException ex) {
            throw new SystemException(Labels.getLabel(Labels.CANNOT_FIND_LOCAL_HOME_OBJECT_MESSAGE), ex);
        } catch (FinderException ex) {
            throw new SystemException(Labels.getLabel(Labels.CANNOT_EXECUTE_ACTION), ex);
        }
    }

    @Override
    protected int getFoundRecordsCount(SearchContext context) throws SystemException {
        try {
            MovieLocalHome movieHome = EntityUtil.getMovieHome();
            int recordsCount = 0;
            if (context.isBasicSearch()) {
                recordsCount = movieHome.getMoviesCount(context.getSearchParameter(BasicSearchAction.SEARCH_PARAMETER));
            } else {
                String title = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.TITLE));
                String countries = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.COUNTRIES));
                String genre = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.GENRE));
                String person = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.PERSON));
                String studio = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.STUDIO));
                Double ratingMin = StringUtil.parseDouble(context.getSearchParameter(AdvancedMovieSearchAction.RATING_MIN));
                Double ratingMax = StringUtil.parseDouble(context.getSearchParameter(AdvancedMovieSearchAction.RATING_MAX));
                String description = StringUtil.getValidValue(context.getSearchParameter(AdvancedMovieSearchAction.DESCRIPTION));
                Integer budgetMin = StringUtil.parseInteger(context.getSearchParameter(AdvancedMovieSearchAction.BUDGET_MIN));
                Integer budgetMax = StringUtil.parseInteger(context.getSearchParameter(AdvancedMovieSearchAction.BUDGET_MAX));
                Integer cashMin = StringUtil.parseInteger(context.getSearchParameter(AdvancedMovieSearchAction.WORLD_CASH_MIN));
                Integer cashMax = StringUtil.parseInteger(context.getSearchParameter(AdvancedMovieSearchAction.WORLD_CASH_MAX));
                recordsCount = movieHome.getMoviesCount(title, countries, genre, person, studio, ratingMin, ratingMax, description, budgetMin, budgetMax, cashMin, cashMax);
            }
            return recordsCount;
        } catch (NamingException ex) {
            throw new SystemException(Labels.getLabel(Labels.CANNOT_FIND_LOCAL_HOME_OBJECT_MESSAGE), ex);
        } catch (FinderException ex) {
            //это не должно произойти
            throw new SystemException(ex);
        }
    }
}
